<?php
namespace app\queen\controller;
use app\common\model\Redis;
use app\common\model\Dev_info;
use app\common\model\Alarm_info;
use app\common\model\User;
use app\common\model\Unit_table;
use app\common\model\IPAttribution;
use app\common\model\Dev_api;
use app\common\model\Alarm_table;
use app\common\model\Wechat;
use app\common\model\Version;
use app\common\model\Dev_data_info;
use think\Controller;
class Upload extends Base{
	
    /**
	 * 数据上传接口
	 * @param [string] v  POST通信协议版本号，不提供默认为2.0
	 * @param [string] dev_id 设备guid1,明文
	 * @param [string] encrypt  load值加密算法，取值AES128、AES256，不提供该键值则默认为明文
	 * @param [string] zip  load值压缩算法，取值gzip，不提供则默认为不压缩
	 * @param [json]    load		携带的数据，以json格式编码
	 */
	public function num(){

		$devinfo = new Dev_info();

		$dev_ids = $this->post["dev_id"];
        // $encrypt = $this->post["encrypt"];

		$load = $this->post["load"];
	
        $select = $this->post["redis_select"];
        $this->recordTime($dev_ids,$select);
        $load = json_decode($load,true);

    	if(!$load){
    	    exit("NO1");
    	}
 
        //频率限制,超过时间,停止
        // if($devinfo->intv($dev_ids,$select)){
        //     exit;
        // }

		//解密
		// $key = $this->redis->hget($dev_id,"key");
		// $res = $this->aes->decrypt($key,$load,$encrypt);
        
        $this->redis->select(1);
        //积累型
        $res = $this->redis->lranges($dev_ids."_his_para");
        //可控型
        $resll_id = $this->redis->lranges($dev_ids."_owner_para");
		foreach ($load as $_k => $_v) {
			//判断dev_id是否存在,不存在则取  $post['dev_id']
			$devid = isset($_v["dev_id"])?$_v["dev_id"]:$dev_ids;

            //查看redis中是否存在,不存在从mysql找,若没有退出,有则保存到redis
            if(!$this->checkRedis($devid)){
                continue;
            }

            //查时区
            $this->redis->select($select);
            $tz = $this->redis->hget($devid,"tz");

            foreach($_v["data"] as $k=>$v){
                
                if(!$v["id"]){
                    //如果操作id不存在则跳出此循环
                    continue;
                }
                //根据操作ID查参数名字,然后进行拼装
                $dev_id = $devid."_".$v["id"]."_data";

                $t0 = $v["t"][0]==0?getTimes():$v["t"][0];
                $v0 = $v["v"][0];
                $this->redis->select(1);

                if(in_array($v["id"],$res)){
                    //积累型数据
                    foreach ($v["v"] as $kl => $vl) {

                        if($kl==0){
                            continue; 
                        }
            			if($v["t"][$kl]){
            			   $t = floatval($t0) + floatval($v["t"][$kl]);
            			}else{
            			   $t = getTimes();
            			}
                        $this->redis->zadd($dev_id,$t, $vl."_".strval($t%1000000));
                    }

                    $this->redis->zadd($dev_id,$t0, $v0."_".strval($t0%1000000));
		
                    //查出设备所在时区,然后算去当天的开始于结束时间
                    $setime = get_today_start_and_end_timestamp_on_the_timezone($tz);
                    //判断是否有跨天数据,如: 判断ABCD16_1_data中数据是否有跨天数据
                    // $resl = $this->redis->zRange($dev_id,0,$setime['st'],true);
                    $resl = $this->redis->zRangeByScore($dev_id,0,$setime['st'],true);

                    if($resl){
                        //将非当天数据存入mysql,先获取表名,再存入数据库,再删除redis
                        $table = get_his_data_table($devid);
                        //获取单位
                        $unit = $devinfo->unit($devid,$v["id"]);
                        $id = $v["id"];
                        $view = in_array($v["id"],$resll_id)?1:0;
                        //用原生的mysqli
                        $mysqli = new \mysqli(config('database.hostname'),config('database.username'),config('database.password'),config('database.database'));
                        foreach($resl as $_ks=>$r){
                            $ks = explode("_", $_ks);
                            //检查连接是否成功
                            $sql = "INSERT INTO $table (`guid1`,`d_id`,`unit`,`val`,`t`,`view`) VALUES('{$devid}','{$id}','{$unit}','{$ks[0]}',$r,'{$view}')";
                            //执行sql语句，完全面向对象的
                            $mysqli->query($sql);
                            //删除跨天数据
                            $this->redis->zrem($dev_id,$_ks);
                        }
                    }
                }else{
		
                    //非积累型数据,先删除后添加
                    $this->redis->zremRangeByRank($dev_id);
                    //传过来多个数据,然后更新最新时间数据
                    if(count($v["v"])>1){
                        $tarr = array($t0);
                        foreach ($v["v"] as $ka => $va) {
                            if($ka==0){
                                continue;
                            }
                            $t = floatval($t0) + floatval($v["t"][$ka]);
                            array_push($tarr,$t);
                        }
                        //获取最新时间
                        $max = max($tarr);
                        $v = $v["v"][array_search($max,$v["t"])];
                        $this->redis->zadd($dev_id,$max,$v."_".strval($t%1000000));
                    }else{
                        //传过来单个值
                        $this->redis->zadd($dev_id,$t0,$v0."_".strval($t0%1000000));
                    }
                }
            }

            //更新该设备最新上传数据时间
            $this->redis->select($select);
            $this->redis->hset($devid,"last_upload",time());
		}

        //启动子进程
        if(chance(config("CHANCE"))){
        // if(chance(30)){
            for($i=0;$i<10;$i++){
                $this->redis->select(0);
                $dev = $this->redis->randomkey();
                $devinfo->redis_cleaner($dev,0);
            }
        }
	    exit("OK");
	}
	
	/**
	 * 可显示字符文件数据上传接口
	 */
	public function file(){

		$devinfo = new Dev_info();

		$dev_id = $this->post["dev_id"];
		$load = $this->post["load"];
        $select = $this->post["redis_select"];

        $this->recordTime($dev_id,$select);
        // $encode = $this->post["encode"];
		// $key = $this->redis->hget($dev_id,"key");

        //文件内容默认为base64解密
        // $encode = $encode?$encode:"base64";

		//解密
		// $res = $this->aes->decrypt($key,$load,$encrypt);
        // 
        $res = json_decode($load,true);
        $this->redis->select(1);
        foreach ($res as $key => $value) {
            $dev_id = $value["dev_id"];
            $data = $value["data"];

            //积累型数据
            $lid = $this->redis->lranges($dev_id."_his_para");
            //可控型
            $resll_id = $this->redis->lranges($dev_id."_owner_para");

            //查出用户uid
            $uid = $devinfo->is_exist($dev_id,"owner");
            $size = 5*1048576;
            $table = get_his_data_table($dev_id);
            
            $path = "upload_file/".$uid["owner"]."/";
            foreach ($data as $_k => $_v) {
                $con = $_v["v"][0];
                $t = $_v["t"][0];
                
                if(!$_v["id"]){
                    //如果操作id不存在则跳出此循环
                    continue;
                }
                 $unit = $this->redis->hget($dev_id."_para_info",$_v["id"]);

                switch ($unit) {
                    case 'sys/file':
                    case 'sys/file-audio':
                    case 'sys/file-video':
                    case 'sys/file-image':
                        //上传文件,文件大小大于5M 则返回代码61
                        $should_len = $_v["size"]?$_v["size"]:-1;
                        if($_v["size"]>$size){
                            continue;
                        }

                        //文件内容base64解密,算出多余字节,并减去多余字节数
                        $con = base64_decode($con);
                        // if($should_len>0){
                        //     $con = substr($con,0,strlen($_v["size"]));
                        // }

                        $_v["type"] = isset($_v["type"])?$_v["type"]:"jpg";

                        $name = $dev_id."_".$t."_".$_v["id"].".".$_v["type"];
                        break;
                    case 'sys/file-pcloud':
                        $name = $dev_id."_".$t."_".$_v["id"].".pcloud";
                        break;
                    case 'sys/file-stl':
                        $con = base64_decode($con);
                        $name = isset($_v["f"])?$_v["f"]:$dev_id."_".$t."_".$_v["id"].".stl";
                        break;
                    case strstr($unit,'sys/file-hz-')==true:
                        $con = base64_decode($con);
                        $name = isset($_v["f"])?$_v["f"]:$dev_id."_".$t."_".$_v["id"].".hz";
                        break;
                    default:
                        continue;
                        break;
                }
                //创建文件夹及目录,写入内容给权限
                saveFile($name,$con,$path);

                if(in_array($_v["id"],$lid)){

                    $view = in_array($v["id"],$resll_id)?1:0;

                    //积累性
                    $name = $path.$name;
                    $mysqli = new \mysqli(config('database.hostname'),config('database.username'),config('database.password'),config('database.database'));
                    $sql = "INSERT INTO $table (`guid1`,`d_id`,`unit`,`bin_str`,`t`,`view`) VALUES('{$dev_id}','{$_v["id"]}','{$unit}','{$name}','{$t}','{$view}')";
                    $mysqli->query($sql);
                }else{

                    //非积累性,先删除
                    $this->redis->zremRangeByRank($dev_id."_".$_v["id"]."_data");
                }
                //保存到redis中以及mysql中
                $this->redis->zadd($dev_id."_".$_v["id"]."_data",$t,$path.$name);

                unset($name);
                unset($con);
            }

            //更新该设备最新上传数据时间
            $this->redis->select($select);
            $this->redis->hset($dev_id,"last_upload",time());

            //10%的触发率
            if(chance(10)){
                $num = count(scandir($path))-2>0?count(scandir($path))-2:0;
                $count = 30;
                //如果超过了
                if($count<$num){
                    //如果查出上传数量,则清除超量文件,先搜索此文件夹下所有文件,并剔除key[0],key[1]
                    $file=scandir($path);
                    // array_splice($file,0,2);
                    //获取文件创建时间并进行降序排序
                    foreach ($file as $_k => $_v) {
                        if($_v=="." || $_v==".."){
                            continue;
                        }
                        $_n[$_k] = filectime($path.$_v);
                        $m[filectime($path.$_v)] = $_v;
                    }
                    sort($_n);
                    for($i=0;$i<$num-$count;$i++){
                        $cfile = explode("_",$m[$_n[$i]]);
                        $this->redis->zrem($cfile[0]."_".$cfile[2],$m[$_n[$i]]);
                        unlink($path.$m[$_n[$i]]);
                    }
                }
            }
        }

	    exit("OK");
	}

    /**
     * 可显字符型数据上传接口
     */
    public function str(){

        $dev_id = $this->post["dev_id"];
        $load = $this->post["load"];

        $select = $this->post["redis_select"];

        $this->recordTime($dev_id,$select);
        // $encode = $this->post["encode"];

        //文件内容默认为base64解密
        // $encode = $encode?$encode:"base64";
        
        $res = json_decode($load,true);

        $this->redis->select(1);
        foreach ($res as $key => $value) {
            $dev_id = $value["dev_id"];
            $data = $value["data"];
            
            $this->redis->select(1);
            //积累型
            $res = $this->redis->lranges($dev_id."_his_para");
            //可控型
            $resll_id = $this->redis->lranges($dev_id."_owner_para");

            $table = get_his_data_table($dev_id);
            foreach ($data as $_k => $_v) {
                //若是二进制文件进行base64解密
                if(strpos($_v["unit"],"sys/state-bin") || $_v["unit"]=="sys/bin"){
                    $v = base64_decode($_v["v"]);
                }else{
                    $v = $_v["v"];
                }
                if(!$_v["id"]){
                    //如果操作id不存在则跳出此循环
                    continue;
                }

                $did = $_v["id"];
                $unit = $_v["unit"];
                $t = $_v["t"];
                
                $t0 = $t[0];
                $v0 = $v[0];
                
                if(in_array($did,$res)){
                    $view = in_array($did,$resll_id)?1:0;
                    //积累型
                    $mysqli = new \mysqli(config('database.hostname'),config('database.username'),config('database.password'),config('database.database'));
                    foreach ($v as $kl => $vl) { 
                        if($kl==0){
                           $ts = $t0;
                        }else{
                           $ts = floatval($t0) + floatval($t[$kl]);
                        }
                        $sql = "INSERT INTO $table (`guid1`,`d_id`,`unit`,`bin_str`,`t`,`view`) VALUES('{$dev_id}','{$did}','{$unit}','{$vl}',$ts,'{$view}')";
                        $mysqli->query($sql);

                        $this->redis->zadd($dev_id."_".$did."_data",$ts,$vl);
                    }
                }else{
                    $this->redis->zremRangeByRank($dev_id."_".$did."_data");
                    $this->redis->zadd($dev_id."_".$did."_data",$t0,$v0);
                }
            }
            //更新该设备最新上传数据时间
            $this->redis->select($select);
            $this->redis->hset($dev_id,"last_upload",time());
        }

        exit("OK");
    }
	
    /**
     * 设备信息描述文件上传接口
     */
	public function devInfoUpload(){

        $dev_id = $this->post["dev_id"];
        $models = isset($this->post["mode"])?$this->post["mode"]:"";
	    $xmlStr = $this->post['load'];

        //file_put_contents("/tmp/log.txt","xml___\r\n".$xmlStr."\r\n\r\n",FILE_APPEND);
	    $xmlOb = simplexml_load_string(htmlspecialchars_decode($xmlStr));

        //XML解析,无法解析则退出
	    if(!$xmlOb) { exit("NO"); }

	    $xmlArr = object_to_array($xmlOb);

        if(!$xmlArr['dev_id']){
            exit("NO");
        }

        // file_put_contents("/tmp/log.txt","xml___\r\n".$xmlOb."\r\n\r\n",FILE_APPEND);
	    // file_put_contents("/tmp/log.txt","aaa___\r\n".$xmlArr."\r\n\r\n",FILE_APPEND);
	    
        //如果设备的经纬度为0则自动获取经纬度
        if($xmlArr['longitude'] == 0 || $xmlArr['latitude'] == 0){
            if($_SERVER['REMOTE_ADDR']){
                $ipQuery = new IPAttribution();
                $res = $ipQuery->IPAttributionQuery($_SERVER['REMOTE_ADDR']);
                $xmlArr['longitude'] = $res['lng'];
                $xmlArr['latitude'] = $res['lat'];
            }
        }
        
        $dev_info = new Dev_info();
        //更新设备的基本信息入mysql
        $flag = $dev_info->where(array('guid1' => $xmlArr['dev_id']))->update(array(
                'name' => $xmlArr['name'],
                'model' => $xmlArr['model'],
                'tz' => $xmlArr['timezone'],
                'longitude' => $xmlArr['longitude'],
                'latitude' => $xmlArr['latitude'],
                'maker' => $xmlArr['maker'],
                'height' => $xmlArr['height'],
                'online_inform'=>isset($xmlArr['keep_online'])?$xmlArr['keep_online']:"-1" 
            ));
        //写入失败则退出,一般表示dev_id 不存在
        if(is_bool($flag)){  exit("NO"); }

        //删除dev_data_info 表中的信息
        $dev_data_info = new Dev_data_info();
        $dev_data_info->del(['guid1'=>$xmlArr['dev_id']]);
        $this->redis->select(1);

        //$_POST[mode]存在并等于clean
        if($models == "clean"){
            $info = $this->redis->hGetAll($xmlArr['dev_id']."_para_info");
            foreach($info as $_k=>$_v){
                $this->redis->del($xmlArr['dev_id']."_".$_k."_data");
            }
        }

        $this->redis->del($xmlArr['dev_id']."_para_info");
        $this->redis->del($xmlArr['dev_id']."_his_para");
        $this->redis->del($xmlArr['dev_id']."_owner_para");

        //判断是否是在线告知,然后进行相应的操作
        if($xmlArr["keep_online"]>0){
            $sel1 = 2;
        }else{
            $sel1 = 0;
        }

        //初始化,切换 redis 数据库
        $this->addRedis($xmlArr['dev_id'],$sel1,$xmlArr['timezone']);
        //记录告知设备最后操作时间
        $this->recordTime($xmlArr['dev_id'],$sel1);

        $this->redis->select($sel1);
        //更新基本信息
        $this->redis->hset($xmlArr['dev_id'],"tz",$xmlArr['timezone']);
        if($xmlArr["keep_online"]>0){
            $this->redis->select(2);
            //算 时间差 为 过期时间
            $this->redis->hset($xmlArr['dev_id'],"online_inform_intv",$xmlArr['keep_online']*60+30);
        }

        $this->redis->select(1);

        //更新设备的参数信息
        if(count($xmlArr['data'][0])==0){
            $xdata = $xmlArr['data'];
            unset($xmlArr['data']);
            $xmlArr['data'][0] = $xdata;
        }

        $unit_table = new Unit_table();

        foreach ($xmlArr['data'] as $k2 => $v2){
            if(!(isset($v2['id']) && isset($v2['name']) && isset($v2['unit']) && isset($v2['storage']))){
                   continue;
            }
            $row = $unit_table->getOne(['val' =>$v2['unit']],'unit_id');
            //查看单位是否存在 不存在就写入
            if($row){
                $unit_id = $row['unit_id'];
            }else{
                $unit_id = $unit_table->insert(array('val' => $v2['unit']));
                if(!$unit_id){
                    continue;
                }
            }
            $ifhis = $v2['storage']=="amass"?1:0;
            $view = isset($v2['view'])?$v2['view']:1;

            $flag = $dev_data_info->insert(array(
                'guid1' => $xmlArr['dev_id'],
                'd_id' => $v2['id'],
                'name' => $v2['name'],
                'unit_id' => $unit_id,
                'if_his' => $ifhis,
                'view'=>$view
            ));
            if(!$flag){ 
                continue; 
            }

            $this->redis->hset($xmlArr['dev_id'].'_para_info',$v2['id'],$v2['unit']);
            
            //将设备所有通知地址存入redis中
            $AlarmModel = new Alarm_info();
            $AlarmModel->addrToRedis($dev_id);
            
            
            if($ifhis=="1"){
                $this->redis->lpush($xmlArr['dev_id']."_his_para",$v2['id']);
            }
            if($view=="1"){
                $this->redis->lpush($xmlArr['dev_id']."_owner_para",$v2['id']);
            }
        }

        if(isset($xmlArr['apis']['api']['id'])){
            $api[0] = $xmlArr['apis']['api'];
        }else {
            $api = $xmlArr['apis']['api'];
        }

        //已覆盖的方式更新，先删除，后更新
        $dev_api = new Dev_api();
        $row  = $dev_api->del(['guid1'=>$xmlArr['dev_id']]);
        $this->redis->select(1);
        //更新设备控制接口信息
        foreach ($api as $k2 => $v2){
            
            $v2["arg"] = isset($v2["arg"])?$v2["arg"]:null;
            if(isset($v2["arg"])){
	    
                if(count($v2["arg"][0])==0){
                    $arg_s[0] = $v2["arg"];
                }else{
                    $arg_s = $v2["arg"];
                }
		
                $arg = json_encode($arg_s);
            }else{
                $arg = null;
            }
    	    //消除变量$arg_s
    	    unset($arg_s);

            //是否显示控制,0 正常显示, 否则不予显示
            $hide = isset($v2['hide'])?$v2['hide']:"0";
            //查看单位是否存在 不存在就写入
            $flag = $dev_api->insert(array(
                'guid1' => $xmlArr['dev_id'],
                'api_id' => $v2['id'],
                'name' => $v2['name'],
                'remark' => $v2['remark'],
                'hide'=>$hide,
                'args' => $arg
            ));
        }

        //首次激活的话更改时间与状态
        //未激活状态条件
        $whe["guid1"] = $xmlArr['dev_id'];
        $whe["a_time"] = "-1";
        $dev_info->updInfo($whe,array('state'=>'active',"a_time"=>time()));
        exit('OK');
	}
	
    /**
     * 设备远程控制信道连接接口
     */
	public function willListen(){
	    
	    $select = $this->post["redis_select"];
	    $this->redis->select($select);

        $this->recordTime($this->post['dev_id'],$select);

	    set_time_limit( 30 );
	    
	    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
	    socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>5, "usec"=>0 ));
	    //端口可重复绑定
	    socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1); 
	    // if(!socket_bind($socket, C('SERVICE_PUBLIC_IP'))) {
	    // 	echo '服务器套接字端口绑定失败';
	    // 	exit;
	    // }
        if(!socket_bind($socket, $_SERVER['SERVER_ADDR'])) {
         echo '服务器套接字端口绑定失败';
         exit;
        } 
	    socket_getsockname($socket, $server_ip, $server_port);
	    socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec"=>3, "usec"=>0 ));
	    
        //查看redis中是否存在
        $flag = $this->redis->isExists($this->post['dev_id']);
        if(!$flag){
            $this->checkRedis($this->post['dev_id']);
        }

	    //更新redis中服务端的ip和port
	    $this->redis->hMset($this->post['dev_id'], array('server_ip' => $server_ip, 'server_port' => $server_port));
	    //及时输出数据，不缓存
	    echo '["'.$server_ip.':'.$server_port.'"]';

        $dbname = config('database.username');
        $dbpwd = config('database.password');

        $cmd = 'nohup php '.LIB_PATH.'Vendor/socket/'.'socket.php '.$server_ip.' '.$server_port.' '.$select.' '.$dbname.' '.$dbpwd.' 1 > /dev/null 2>&1 &';

	    exec($cmd);
	    socket_close($socket);    
	}

    /**
     * 设备警报上传接口
     * @return [type] [description]
     */
    public function devAlarmUpload(){
        $dev_id = $this->post["dev_id"];
        $load = $this->post["load"];
        $select = $this->post["redis_select"];
        
        $this->recordTime($dev_id, $select);
        $load = json_decode($load, true);
        $id = $load["id"];
        $level = $load["level"] ? $load["level"] : 0;
        $code = $load["code"];
        $reason = $load["reason"];
        $alarmModel = new Alarm_table();

        $time = time();

        $this->redis->select($select);

        $last_alarm_inform_t = $this->redis->hget($dev_id, "last_alarm_inform_t");
        $intv = $this->redis->hget($dev_id, "intv");
        $cur_alarm_no = $this->redis->hget($dev_id, "cur_alarm_no");
        if($cur_alarm_no == "-1"){

            //无警报则写入到mysql中
            $add = array(
               'alarm_id' => $time.'_'.$id,
               'code' => $code,
               'guid1' => $dev_id,
               'reason' => $reason,
               'level' => $level,
               'alarm_type' => 'abnormal',
               'st' => $time
            );
            
            if(FALSE === $alarmModel->save($add)){
                exit('OK');
            }else {
                $this->redis->hset($dev_id, 'cur_alarm_no', $id);
                $this->redis->hset($dev_id, 'alarm_t', $time);
            }
        }else{
            $alarm_t = $this->redis->hget($dev_id, 'alarm_t');
            if($id == $cur_alarm_no){
                // 上传频率限制
                if($time - $last_alarm_inform_t < $intv*60){
                    exit('OK');
                }

                $atable = $alarmModel->updInfo(['alarm_id' => $alarm_t.'_'.$id],['et'=>$time]);
                if(!$atable){
                    exit('OK');
                }
            }else{
                //旧警报自动解除,并先复原redis
                $flag = $alarmModel->updInfo(['alarm_id' => $alarm_t.'_'.$cur_alarm_no],['et' => $time, 'state' => 'end']);
                if(!$flag){
                    exit('OK');
                }
            
                // 新警报写入mysql,并且更新reids
                $add = array(
                    'alarm_id' => $time . "_" . $id,
                    'code' => $code,
                    'guid1' => $dev_id,
                    'reason' => $reason,
                    'level' => $level,
                    'alarm_type' => 'abnormal',
                    'st' => $time
                );
                if(FALSE === $alarmModel->save($add)) die('OK');
            
                $this->devRestoreUpload($dev_id, $select);
                //记录新的警报id,时间
                $this->redis->hset($dev_id, 'cur_alarm_no', $id);
                $this->redis->hset($dev_id, 'alarm_t', $time);
            }
        }

        //获取发送警报标志位
        $alarm_temp_valid = $this->redis->hget($dev_id, 'alarm_temp_valid');
        $alarm_valid = $this->redis->hget($dev_id, 'alarm_valid');
        if($alarm_temp_valid == 'N' || $alarm_valid == 'N') die('OK');

        //判断发送次数是否已达发送警报阀值
        $alarm_has_send_num = $this->redis->hget($dev_id, 'alarm_has_send_num');
        $alarm_send_num = $this->redis->hget($dev_id, 'alarm_send_num');
        if($alarm_has_send_num >= $alarm_send_num){
            $this->redis->hset($dev_id, 'alarm_temp_valid', 'N');
            die('OK');
        }

        //更新last_alarm_inform_t,alarm_has_send_num自增1,alarm_msg
        $this->redis->hset($dev_id, 'last_alarm_inform_t', $time);
        $this->redis->hset($dev_id, 'alarm_has_send_num', $alarm_has_send_num+1 );
        $this->redis->hset($dev_id, 'alarm_msg', $reason);

        //发送警报
        $alarmModel->sendA($dev_id, 1);
        echo 'OK';
    }

    /**
     * 设备警报撤销接口
     * @return [type] [description]
     */
    public function devNormalUpload(){
        
        $dev_id = $this->post["dev_id"] ;
        $load = $this->post["load"];
        $select = $this->post["redis_select"];

        $load = json_decode($load,true);
        $time = time();

        $this->redis->select($select);
        $this->recordTime($dev_id,$select);

        $alarm_t = $this->redis->hget($dev_id,"alarm_t");
        $cur_alarm_no = $this->redis->hget($dev_id,"cur_alarm_no");

        if($cur_alarm_no=="-1"){
            exit("NO");
        }

        $alarmModel = new Alarm_table();

        $save["et"] = $time;
        $save["state"] = "end";
        $alarmModel->updInfo(["alarm_id"=>$alarm_t."_".$load["id"]],$save);
        //reids复原
        $this->devRestoreUpload($dev_id,$select);

        //警报撤销
        $devModel = new Alarm_table();
        $devModel->sendA($dev_id, 2);
	    echo 'OK';
    }

    /**
     * 警报Redis复原
     * @param  [type] $dev_id [description]
     * @param  [type] $select [descriptionF]
     * @return [type]         [description]
     */
    public function devRestoreUpload($dev_id,$select){
        $this->redis->select($select);
        $this->redis->hset($dev_id, 'alarm_temp_valid', 'Y');
        $this->redis->hset($dev_id, 'last_alarm_inform_t', '0');
        $this->redis->hset($dev_id, 'alarm_has_send_num', '0');
        $this->redis->hset($dev_id, 'cur_alarm_no', '-1');
        $this->redis->hset($dev_id, 'alarm_msg', '');
    }

    /**
     * 设备在线告知接口
     */
    public function online(){
        
        $dev_id = $this->post["dev_id"];
        $time = time();
        
        $this->redis->select(2);

        $this->recordTime($dev_id,2);
 
        //5.5分钟
        $ctime = config("DEV_TIMES_ONLINE");

        $last_online_inform_t = $this->redis->hget($dev_id,"last_online_inform_t");

        $if_save = $this->redis->hget($dev_id,"if_save");

        if($time-$last_online_inform_t>$ctime){
        
            $alarmModel = new Alarm_table();
            if($if_save=="1"){

                 $where["guid1"] = $dev_id;
                 $where["et"] = "-1";
                 $info = $alarmModel->getAll($where,'st desc',1,[],'alarm_id');
                 $info = endoceArr($info);

                 $alarmModel->updInfo(["alarm_id"=>$info[0]["alarm_id"]],["et"=>$time,"state"=>"end"]);
            }elseif($if_save=="0"){
                 
                 //掉线通知
                 $wetchatModel = new Weixin();
                 $wetchatModel->wechat_send($dev_id,3);

                 $this->redis->hset($dev_id,"if_save","1");

                 $st = $this->redis->hget($dev_id,"last_online_inform_t");

                 $add = array(
                    "alarm_id"=>$time,
                    "guid1"=>$dev_id,
                    "st"=>$st,
                    "et"=>$time,
                    "alarm_type"=>"offline",
                    "state"=>"end"
                 );
                 $alarmModel->save($add);
            
            }
        }

        //掉线记录复原
        $this->restore($dev_id);
	
	    exit("OK");
    }

    /**
     * 掉线记录复原
     * @return [type] [description]
     */
    public function restore($dev_id){

        $this->redis->select(2);
        $this->redis->hset($dev_id,"last_online_send_t","0");
        $this->redis->hset($dev_id,"online_inform_temp_valid","Y");
        $this->redis->hset($dev_id,"online_inform_has_send_num","0");
        $this->redis->hset($dev_id,"if_save","0");
        $this->recordTime($dev_id,2);
    }

    /**
     * 记录在线告知设备最后在线时间
     * @param  [string] $dev_id [设备号]
     * @param [string] $select [几号数据库]
     */
    public function recordTime($dev_id,$select){
        
        if($select=="2"){
            $this->redis->select(2);
            $this->redis->hset($dev_id,"last_online_inform_t",time());
        }
    } 

    /**
     * 设备版本更新
     * @param [string] load [版本号]
     */
    public function devupdate(){
        //load 版本号
        $dev_id = $this->post["dev_id"];
        $load = $this->post["load"];

        //查型号,查拥有人
        $devModel = new Dev_info();
        $uid = $devModel->getOne(["guid1"=>$dev_id],'model,owner,apply_id');

        $version = db('version');
        
        $where["model"] = $uid["model"];
        $where["uid"] = $uid["apply_id"];
        $res = $version->where($where)->field("v_name,st")->select();

        if(!$res){
            exit('["NO"]');
        }

        $v_name = "";
        foreach ($res as $k => $v) {
            if($v["v_name"]>$load){
                //查看此文件夹下有多少文件
                $v_name = $v["v_name"];
                break;
            }
        }
        if($v_name){
                $where["v_name"] = $v_name;
                $num = $version->where($where)->field("file_path")->select();
                if(count($num)>1){
                    //说明文件夹下 有多个文件
                    $len = strrpos($num[0]["file_path"],"/");
                    $fileName = substr($num[0]["file_path"],0,$len+1);

                    exit('["'.$fileName.'"]');
                }else{
                    //单个文件 全路径
                    exit('["'.$num[0]["file_path"].'"]');
                }
        }else{
            exit('["NO"]');
        }
    }
    
    /**
     * 获取tcp长连接地址
     */
    
    public function getTcpServerAddr() {
        echo '[www.mydehui.com:6200]';
    }
    
    /**
     * 获取设备tcp长连接地址
     */
	public function Authentication(){
	    $dev_id = $this->post['dev_id'] ;
	    //form 格式 ip:port
	    //\Think\Log::write('test222'.file_get_contents('php://input'));
	    \Think\Log::write('test3'.$this->post['from'].json_encode($_POST));
	    $explode = explode(':', $this->post['from']);
	    //查出设备在redis中几号数据库

        $select = $this->redis->whereRedis($dev_id);
        
        if(is_bool($select)){
            exit("NO");
        }
        
        //切换数据库
        $this->redis->select($select);

        //设置ip、port
        $devip = $this->redis->hset($dev_id, "dev_ip", 'tcp_'.$explode[0]);
        preg_match('#\d*#', $explode[1], $port);
        $devport = $this->redis->hset($dev_id, 'dev_port', $port[0]);
	    echo "auth=$dev_id\r\n";    
	}
	
	
}

?>